package com.aispeech.astools.view;

import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;

import com.aispeech.astools.ASTApplication;
import com.aispeech.astools.R;
import com.aispeech.astools.recorder.InterruptRecord;
import com.aispeech.astools.recorder.RecordListener;
import com.aispeech.astools.service.SerialTestService;
import com.aispeech.astools.service.SerialTestService.MutualBinder;
import com.aispeech.astools.service.SerialTestService.SerialCallBack;
import com.aispeech.astools.utils.AudioFileWrite;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import androidx.appcompat.app.AppCompatActivity;

public class Serial3308Activity extends AppCompatActivity {

    private final String TAG = "Serial3308Activity";

    //3308 usb device info
    private final int VID = 8711;
    private final int PID = 25;


    private EditText mEtSerialPort;
    private Button mBtnOpen;
    private Spinner mSpBaudRate;
    private ListView mLv;

    private BaseAdapter mAdapter;
    private List<String> mList = new ArrayList<>();
    private String mSerialPortPath = "/dev/ttyACM0";
    private int mBaudRate = 1500000;

    private AudioFileWrite mAudioFile;
    private final String externalStorageDirectory = Environment.getExternalStorageDirectory().getAbsolutePath();
    private final String AudioFilePath = externalStorageDirectory + File.separator + "aispeech" + File.separator + "serial.pcm";

    private SerialTestService.MutualBinder mutualBinder;
    private InterruptRecord mIntRecord;


    private SerialCallBack mScb = new SerialCallBack() {
        @Override
        public void onData(byte[] data) {
            mAudioFile.writeBuffer(data);
        }

        @Override
        public void onMessage(String event) {
            showIOData("msg", event);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_serial3308);

        mutualBinder = (MutualBinder) ASTApplication.getServiceBinder(ASTApplication.SERIAL_SERVICL_BINDER);

        initView();

        mAudioFile = new AudioFileWrite(getApplication());
        mAudioFile.startWrite(AudioFilePath);

        initHid();

//        Log.d(TAG, "onCreate: init systemSerialRecord");
//        SystemSerialRecord systemSerialRecord = new SystemSerialRecord();
//        systemSerialRecord.init(getApplication(), null);
    }

    private void initHid() {
        mIntRecord = new InterruptRecord(VID, PID);
        mIntRecord.init(getApplication(), new RecordListener() {
            @Override
            public void onBuffer(byte[] data) {
                Log.d(TAG, "onBuffer with: data = " + byteToStr(data) + "");
                showIOData("wakeup", byteToStr(data));
            }

            @Override
            public void onEvent(EVENT event) {
                showIOData("event", event + "");
            }

            @Override
            public void onError(String info) {
                showIOData("err", info);
            }
        });

        mIntRecord.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
        if (null != mutualBinder && (!mutualBinder.isOpen())) {
            mutualBinder.closePort();
            if (null != mAudioFile) {
                mAudioFile.closeWrite();
            }
        }
        if (null != mIntRecord) {
            mIntRecord.destroy();
        }
    }


    private void initView() {
        mEtSerialPort = findViewById(R.id.et_3308_port_name);
        mBtnOpen = findViewById(R.id.btn_3308_open);
        mBtnOpen.setText(mutualBinder.isOpen() ? "close" : "open");
        mBtnOpen.requestFocus();
        mBtnOpen.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mutualBinder.isOpen()) {
                    mutualBinder.closePort();
                    showIOData("msg", "close port");
                } else {
                    mSerialPortPath = mEtSerialPort.getText().toString().trim();
                    if (TextUtils.isEmpty(mSerialPortPath)) {
                        showIOData("err", "please input valid port name");
                        return;
                    }

                    if (mBaudRate <= 0) {
                        showIOData("err", "please select valid baudrate");
                        return;
                    }

                    mutualBinder.openPort(mSerialPortPath, mBaudRate, mScb);
                    showIOData("msg", "open port" + " : " + mutualBinder.isOpen());
                }
                mBtnOpen.setText(mutualBinder.isOpen() ? "close" : "open");
            }
        });

        mSpBaudRate = findViewById(R.id.sp_3308_baudrate);
        mSpBaudRate.setSelection(14);
        mSpBaudRate.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                mBaudRate = Integer.parseInt(getResources().getStringArray(R.array.baudrate_array)[position]);
                Log.d(TAG, "onItemSelected with: position = " + position + ", mBaudRate = " + mBaudRate);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        mLv = findViewById(R.id.lv_3308_info);
        mAdapter = new LvAdapter();
        mLv.setAdapter(mAdapter);

    }

    private String byteToStr(byte[] buffer) {
        try {
            int length = 0;
            for (int i = 0; i < buffer.length; ++i) {
                if (buffer[i] == 0) {
                    length = i;
                    break;
                }
            }
            return new String(buffer, 0, length, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    private void showIOData(final String type, final String data) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mList.add(type + " : " + data);
                mAdapter.notifyDataSetChanged();
                mLv.setSelection(mList.size() - 1);
            }
        });
    }

    private class LvAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return mList == null ? 0 : mList.size();
        }

        @Override
        public Object getItem(int i) {
            if (null != mList) {
                mList.get(i);
            }
            return null;
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View getView(int i, View convertView, ViewGroup viewGroup) {
            ViewHolder viewHolder;
            if (convertView == null) {
                convertView = Serial3308Activity.this.getLayoutInflater().inflate(R.layout.lv_info_item, null);
                viewHolder = new ViewHolder(convertView);
                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }
            viewHolder.tvInfo.setText(mList.get(i));
            return convertView;
        }
    }

    private final class ViewHolder {

        TextView tvInfo;

        ViewHolder(View view) {
            tvInfo = view.findViewById(R.id.tv_info);
        }
    }

}
